#ifndef QTBOX2DSCENE_H
#define QTBOX2DSCENE_H

#include "Box2D/Box2D.h"
#include "qtpropertymanager.h"
#include "qteditorfactory.h"
#include "qttreepropertybrowser.h"
#include "qtbuttonpropertybrowser.h"
#include "qtgroupboxpropertybrowser.h"
#include "qtvariantproperty.h"

#include <QtGui/QGraphicsScene>
#include <QtCore/QMap>
#include <QDataStream>
#include <QtCore/QList>
#include <QtCore/QVariant>
#include <QImage>
#include <QAction>
#include <QTimer>
#include <QtCore/QSharedMemory>

class QtBox2DScene;
class QtBox2DAbstractItem;
class QtBox2DBaseItem;
class UndoNode;

class QtBox2DScene : public QGraphicsScene
{
	Q_OBJECT
public:
	QtBox2DScene(QObject* parent = 0);
	virtual ~QtBox2DScene();

	void loadImages();
	const QMap<QString,QImage*>& getImages() const { return mImages; };
	QtBox2DBaseItem* getItem(const QString& itemName) const ;
	const QStringList getSelectedNames() const;

	void initBox2DWorld(b2World* pWorld, int velocityIterations=6, int positionIterations=2);
	b2World* getWorld() const { return mWorld; };
	bool isStart() const { return mIsStart; };

	QList<QtBox2DAbstractItem*> loadItemsFromDataStream(QDataStream& dataStream, bool bLoadFromFile = false, bool bPaste = false);

	void pushUndoNormal(const QStringList& itemNames, const QString& itemProperty, 
		const QVariant& undoValue);
	void pushRedoNormal(const QString& itemProperty, const QVariant& redoValue);
	void pushUndoAddOrRemove(const QStringList& itemNames, bool bAdd);
	void deleteItems(const QStringList& nameList);
	void deleteItems(const QList<QGraphicsItem*>& itemList);
protected:
	virtual void mousePressEvent(QGraphicsSceneMouseEvent *event);
	void clearUndoRedo(bool bUndo);
signals:
	void start(bool bStart);
	void updateBodys();
	void changeProperties(const QList<QWidget*>& widgets);
	void enableUndo(bool);
	void enableRedo(bool);
public slots:
	virtual void newFile();
	virtual void save();
	virtual void saveAs();
	virtual void load();
	void copy();
	void cut();
	void paste();

	void undo();
	void redo();

	QtBox2DAbstractItem* createItem(QAction* action);
	void deleteItem();

	void updateWorld();
	void selectionChange();
	void setProperty(QtProperty *prop, const QVariant &value);

	void startSlot(bool bStart);

	void setMousePos(const QPoint& mousePos) { mMousePos = mousePos; };
private:

	QString  mFileName;

	QPoint mMousePos;
	QSharedMemory mSharedMemory;

	QTimer* mTimer;

	// Construct a world object, which will hold and simulate the rigid bodies.
	b2World* mWorld;
	bool     mIsStart;
	int mVelocityIterations;
	int mPositionIterations;


	QtAbstractPropertyBrowser* mPropertyWidget;
	QtVariantPropertyManager* mVariantManager;
	QtVariantProperty*        mGravityProperty;

	QMap<QString,QImage*> mImages;
	QList<UndoNode*>       mUndoList;
	QList<UndoNode*>       mRedoList;
};
#endif